<?php
/**
 * Useful functions, used throughout the framework.
 * 
 * Copyright (c) 2006-2007, Julien PORTALIER
 *
 * Some functions are derived from CakePHP,
 * Copyright (c) 2006, Cake Software Foundation, Inc.
 * @link http://cakephp.org/
 * 
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 * 
 * @copyright    Copyright (c) 2006-2007, Julien PORTALIER
 * @link         http://featherphp.googlecode.com/
 * @license      http://www.opensource.org/licenses/mit-license.php The MIT License
 */

# arrays

/**
 * Sanitizes an array by removing magic quotes.
 */
function & cleanArray(&$a)
{
#	if (get_magic_quotes_gpc())
		__cleanArray($a);
	return $a;
}

function __cleanArray(&$a)
{
	if (is_array($a))
	{
		foreach(array_keys($a) as $k)
			__cleanArray($a[$k]);
	}
	else {
		$a = stripslashes($a);
	}
}


/**
 * Computes the intersection of arrays by comparing keys.
 */
function & array_intersect_keys(array $arr, array $keys)
{
	$rs = array();
	foreach($arr as $k => $v)
	{
#		echo $k;
		if (in_array($k, $keys))
			$rs[$k] = $v;
	}
	return $rs;
}

/**
 * Permits to work with lists in array or string (comma separated) forms.
 * 
 * @return Array
 * @param $arr Mixed array or string.
 * @param $split String Token separators.
 */
function & array_list($arr, $split=',;')
{
	if (!is_array($arr))
		$arr = preg_split('/[,;]/', $arr, -1, PREG_SPLIT_NO_EMPTY);
	foreach($arr as $k => $v)
	{
		$v = trim($v);
		
		if (empty($v))
			unset($arr[$k]);
		else
			$arr[$k] = $v;
	}
	$arr = array_unique($arr);
	return $arr;
}

/**
 * Merges arrays recursively.
 * 
 * @return Array Merged array.
 * @param $arr1 Array
 * @param $arr2 Array
 * @param $arrN Array Variable list of arrays.
 */
function & array_recursive_merge(array $arr1, array $arr2)
{
	$arrays = func_get_args();
	$left   = array_shift($arrays);
	
	while(!empty($arrays))
	{
		$right = array_shift($arrays);
		foreach($right as $k => $v)
		{
			foreach ($v as $kk => $vv)
				$left[$k][$kk] = $vv;
		}
	}
	return $left;
}

/*
function implode_with_keys($glue, $linefeed, array &$arr)
{
	$data = '';
	foreach ($arr as $k => $v)
		$data .= $k.$glue.$v.$linefeed;
	return $data;
}
*/

# useful functions

/**
 * Seeks an environment variable.
 */
function env($key)
{
	if     (isset($_SERVER["ORIG_$key"])) return $_SERVER["ORIG_$key"];
	elseif (isset($_SERVER[$key]))        return $_SERVER[$key];
	elseif (isset($_ENV[$key]))           return $_ENV[$key];
	elseif (getenv($key) !== false)       return getenv($key);
	return null;
}

/**
 * Will print out any PHP variable. 
 */
function debug()
{
	if (!DEBUG)
		return;
	foreach (func_get_args() as $v)
	{
		echo '<pre>';
		print_r($v);
		echo '</pre>';
	}
}

/**
 * Records a log into specified log file.
 */
function file_log($text, $log='default')
{
	Load::libs('log');
	$_log = Log::instance()->write($text, $log);
}

/**
 * Reads cached data, or saves data for caching.
 * 
 * @param  $path    string Cached file.
 * @param  $data    string Data to be cached (null if reading).
 * @param  $expires mixed Cached data lifetime.
 * @param  $target  string cache|public|apc Save cached file in app/empt/cache, app/webroot or in memory?
 * @return string cached data or false.
 */
function cache($path, $data=null, $expires=Core::cache_lifetime, $target='cache')
{
	if (is_null($expires))
		$expires = Core::cache_lifetime;
	
	switch (strtolower($target))
	{
		case 'apc':
			# if APC is present:
			if (function_exists('apc_fetch'))
			{
				$key = APP.'tmp'.DS.'cache'.DS.$path;
				if (is_null($data))
				{
					# read cache
					$data = apc_fetch($key);
					return ($data !== false) ? unserialize($data) : false;
				}
				else
				{
					# save cache
					if (is_string($expires))
						$expires = strtotime($expires);
					return apc_store($key, serialize($data), $expires);
				}
			}
			# fallback on filecache
			
		case 'cache':
			$filename = APP.'tmp'.DS.'cache'.DS.$path;
			break;
		
		case 'public':
			$filename = APP.'webroot'.DS.$path;
			break;
	}
	
	if (is_null($data))
	{
		# read cache from file
		if (file_exists($filename))
		{
			$now = time();
			if (is_string($expires))
				$expires = strtotime($expires);
			if (filemtime($filename) + ($expires - $now) < $now)
			{
				# cache has expired
				@unlink($filename);
				return false;
			}
			else
			{
				# cache is good!
				return unserialize(file_get_contents($filename));
			}
		}
	}
	else
	{
		# save cache into file
		return file_put_contents($filename, serialize($data), LOCK_EX);
	}
	
	return false;
}

/**
 * Saves an array as an INI file.
 */
function write_ini_file($file, array $arr)
{
	if ($fh = fopen($file, 'w'))
	{
		foreach($arr as $k => $v)
		{
			if (is_array($v))
			{
				fwrite($fh, "[$k]\n");
				foreach($arr[$k] as $k => $v)
					fwrite($fh, "$k=$v\n");
				fwrite($fh, "\n");
			}
			else {
				fwrite($fh, "$k=$v\n");
			}
		}
		return true;
	}
	return false;
}

/**
 * Finds an image file which may have multiple extensions.
 * You may use it to find any kind of files, thought.
 * 
 * @param  string $path
 * @param  string $extensions  File may have one of these extensions.
 * @return mixed  Full path to file (null if no file was found). 
 */
function getImage($path, $extensions='gif,jpg,png')
{
	$files = glob($path.'.{'.$extensions.'}', GLOB_NOSORT | GLOB_BRACE);
	return isset($files[0]) ? $files[0] : null;
}

/*
function exec_cmd($cmd, $stdin, &$stdout)
{
	$descriptors = array(
		array('pipe', 'r'),             // stdin
		array('pipe', 'w'),             // stdout
		array('file', '/dev/null', 'a') // stderr
	);
	$proc = proc_open($cmd, &$descriptors, &$pipes);
	
	if (is_resource($proc))
	{
		// sends data to stdin
		fwrite($pipes[0], $stdin);
		fclose($pipes[0]);
		
		// receives output from stdout
		while(!feof($pipes[1]))
			$stdout .= fgets($pipes[1], 1024);
		fclose($pipes[1]);
		
		// ends process
		return proc_close($proc);
	}
	return false;
}
*/
?>